Exxon Mobil Corporation, is an American multinational oil and gas corporation headquartered in Irving, Texas.
The company explores for and produces crude oil and natural gas in the United States, Canada/South America, Europe, Africa, Asia, and Australia/Oceania. It also manufactures and markets commodity petrochemicals, including olefins, aromatics, polyethylene and polypropylene plastics, and specialty products; and transports and sells crude oil, natural gas, and petroleum products. Exxon Mobil Corporation was formerly known as Exxon Corporation and changed its name to Exxon Mobil Corporation in November, 1999.
A trend of bearish technical signs has been illustrated by Exxon Mobil Corp. (XOM). We are careful as global oil prices continue to fall and production is still at a very high historical level.
In the second quarter, Exxon Mobil Corp.'s profit dropped by half on sharply lower oil and gas prices around the world, but the company's oil and gas production, which has typically declined in recent years, increased.
In this project, we analyze the ExxonMobil’s stock price with respect to its competitors and predict the Exxon’s stock price.
The data is obtained from Yahoo finance. The dataset consists of stock market data of XOM from Nov 30, 2010 to Nov 30, 2020.
| Attribute Name | Description |
|---|---|
| Date | Date in yyyy-mm-dd |
| High | Highest price at which a stock traded during a period |
| Low | lowest price at which a stock traded during a period |
| Close | Price of an individual stock before the stock closes for the day |
| Volume | total number of shares traded in a security over a period |
| Adj Close | Adjusted closing price amends a stock's closing price to reflect that stock's value after accounting for any corporate actions |
#Install the dependencies
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
import datetime
import seaborn as sns
import os
from pandas_datareader import data, wb
from pandas.util.testing import assert_frame_equal
from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.svm import SVR
import keras
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
from keras.layers import *
from keras.callbacks import EarlyStopping
import plotly
import chart_studio
import chart_studio.plotly as py
import cufflinks as cf
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode(connected=True)
import plotly.graph_objs as go
import plotly.offline as offline
offline.init_notebook_mode()
from fbprophet import Prophet
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
from pylab import rcParams
rcParams['figure.figsize'] = 10, 6
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.arima_model import ARIMA
import pmdarima
from pmdarima.arima import auto_arima
start = datetime.datetime(2010,11,30)
end = datetime.datetime(2020,11,30)
ticker = "XOM"
data =data.DataReader(ticker,'yahoo',start,end)
data
We reset the index to get the Date as a new column, then we check the for null values and data types of our attributes.
df = data
df.reset_index(inplace = True)
df
df.info()
#Plotting Open, Close, High, Low to see how they vary over the given time period
trace_open = go.Scatter(
x = df["Date"],
y = df["Open"],
mode = 'lines',
name="Open"
)
trace_high = go.Scatter(
x = df["Date"],
y = df["High"],
mode = 'lines',
name="High"
)
trace_low = go.Scatter(
x = df["Date"],
y = df["Low"],
mode = 'lines',
name="Low"
)
trace_close = go.Scatter(
x = df["Date"],
y = df["Close"],
mode = 'lines',
name="Close"
)
data = [trace_open,trace_high,trace_low,trace_close]
layout = go.Layout(title="XOM Stock Price",xaxis_rangeslider_visible=True)
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
#Plotting Volume over the given time period
trace_volume = go.Scatter(
x = df["Date"],
y = df["Volume"],
mode = 'lines',
name="Volume"
)
data_volume = [trace_volume]
layout_volume = go.Layout(title="Volume",xaxis_rangeslider_visible=True)
fig_volume = go.Figure(data=data_volume,layout=layout_volume)
plotly.offline.iplot(fig_volume)
Perhaps the most common graphical way of displaying commodities price behavior in a giving time frame, candlestick graphs allows us to get a quick and intuitive perception on the stock’s performance. Each candle represents a specific period of analysis and informs the opening and closing prices, as well as it’s highs and lows.
trace = go.Candlestick(x = df['Date'].tolist(),
open = df['Open'].values.tolist(),
high = df['High'].values.tolist(),
low = df['Low'].values.tolist(),
close = df['Close'].values.tolist(),
increasing=dict(line=dict(color= '#58FA58')),
decreasing=dict(line=dict(color= '#FA5858')))
layout = go.Layout(title="XOM Historical Price",
xaxis_rangeslider_visible=False,
yaxis= {'title': 'Stock Price'}
)
data = [trace]
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
#Plotting close price
plt.figure(figsize=(10,6))
plt.grid(True)
plt.xlabel('Dates')
plt.ylabel('Close Prices')
plt.plot(df['Close'])
plt.title('XOM closing price')
plt.show()
df_close = df['Close']
df_close.plot(style='k.')
plt.title('Scatter plot of closing price')
plt.show()
A given time series is thought to consist of three systematic components including level, trend, seasonality, and one non-systematic component called noise.
These components are defined as follows:
The Dickey-Fuller test is one of the most popular statistical tests. It can be used to determine the presence of unit root in the series, and hence help us understand if the series is stationary or not. The null and alternate hypothesis of this test is:
Null Hypothesis: The series has a unit root (value of a =1)
Alternate Hypothesis: The series has no unit root.
If we fail to reject the null hypothesis, we can say that the series is non-stationary. This means that the series can be linear or difference stationary.
If both mean and standard deviation are flat lines(constant mean and constant variance), the series becomes stationary.
So let's check for stationarity:
#Test for staionarity
def test_stationarity(timeseries):
#Determing rolling statistics
rolmean = timeseries.rolling(12).mean()
rolstd = timeseries.rolling(12).std()
#Plot rolling statistics:
plt.plot(timeseries, color='blue',label='Original')
plt.plot(rolmean, color='red', label='Rolling Mean')
plt.plot(rolstd, color='black', label = 'Rolling Std')
plt.legend(loc='best')
plt.title('Rolling Mean and Standard Deviation')
plt.show(block=False)
print("Results of dickey fuller test")
adft = adfuller(timeseries,autolag='AIC')
# output for dft will give us without defining what the values are.
#hence we manually write what values does it explains using a for loop
output = pd.Series(adft[0:4],index=['Test Statistics','p-value','No. of lags used','Number of observations used'])
for key,values in adft[4].items():
output['critical value (%s)'%key] = values
print(output)
test_stationarity(df_close)
Through the above graph, we can see the increasing mean and standard deviation and hence our series is not stationary.
We see that the p-value is greater than 0.05 so we cannot reject the Null hypothesis. Also, the test statistics is greater than the critical values.Hence, the data is non-stationary.
In order to perform a time series analysis, we may need to separate seasonality and trend from our series. The resultant series will become stationary through this process.
So let us separate Trend and Seasonality from the time series.
result = seasonal_decompose(df_close, model='multiplicative', freq = 30)
fig = plt.figure()
fig = result.plot()
fig.set_size_inches(16, 9)
We start by taking a log of the series to reduce the magnitude of the values and reduce the rising trend in the series. Then after getting the log of the series, we find the rolling average of the series. A rolling average is calculated by taking input for the past 12 months and giving a mean consumption value at every point further ahead in series.
from pylab import rcParams
rcParams['figure.figsize'] = 10, 6
df_log = np.log(df_close)
moving_avg = df_log.rolling(12).mean()
std_dev = df_log.rolling(12).std()
plt.legend(loc='best')
plt.title('Moving Average')
plt.plot(std_dev, color ="black", label = "Standard Deviation")
plt.plot(moving_avg, color="red", label = "Mean")
plt.legend()
plt.show()
We are creating a variable called forecast_out, to store the number of days (30 days) into the future that we want to predict. This variable will be used through out the program so that we can simply change the number and the rest of the program will correspond accordingly.
Pros:
Cons:
df1 = df[['Close']]
We also need a column (the target or dependent variable) that will hold the predicted price values 30 days into the future. The future price that we want that’s 30 days into the future is just 30 rows down from the current Close price. So we will create a new column called ‘Prediction’ and populate it with data from the Close column but shifted 30 rows up to get the price.
# A variable for predicting 'n' days out into the future
forecast_out = 30 #'n=30' days
#Create another column (the target ) shifted 'n' units up
df1['Prediction'] = df1[['Close']].shift(-forecast_out)
#print the new data set
print(df1.tail())
### Create the independent data set (X) #######
# Convert the dataframe to a numpy array
X = np.array(df1.drop(['Prediction'],1))
#Remove the last '30' rows
X = X[:-forecast_out]
print(X)
### Create the dependent data set (y) #####
# Convert the dataframe to a numpy array
y = np.array(df1['Prediction'])
# Get all of the y values except the last '30' rows
y = y[:-forecast_out]
print(y)
# Split the data into 75% training and 25% testing
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# Create and train the Linear Regression Model
lr = LinearRegression()
# Train the model
lr.fit(x_train, y_train)
# Testing Model: Score returns the coefficient of determination R^2 of the prediction.
# The best possible score is 1.0
lr_confidence = lr.score(x_test, y_test)
print("lr confidence: ", lr_confidence)
# Set x_forecast equal to the last 30 rows of the original data set from Adj. Close column
x_forecast = np.array(df1.drop(['Prediction'],1))[-forecast_out:]
# Print linear regression model predictions for the next '30' days
lr_prediction = lr.predict(x_forecast)
print(lr_prediction)
x_forecast_dict = dict(enumerate(x_forecast.flatten(), 1))
lr_pred_dict = dict(enumerate(lr_prediction.flatten(), 1))
forecast = pd.DataFrame()
forecast['x_forecast'] = x_forecast_dict.values()
forecast['lr_prediction'] = lr_pred_dict.values()
#Visualize the data
predictions = lr_prediction
#Plot the data
valid = df1[X.shape[0]:]
valid['Predictions'] = predictions #Create a new column called 'Predictions' that will hold the predicted prices
plt.figure(figsize=(25,10))
plt.title('Model')
plt.xlabel('Days',fontsize=18)
plt.ylabel('Close Price USD ($)',fontsize=18)
plt.plot(df1['Close'])
plt.plot(valid[['Close','Predictions']])
plt.legend(['Train', 'Val', 'Prediction' ], loc='upper right')
plt.show()
trace_open = go.Scatter(
x = df.iloc[-30:, 0],
y = forecast['x_forecast'],
mode = 'lines',
name="True",
)
trace_high = go.Scatter(
x = df.iloc[-30:, 0],
y = forecast['lr_prediction'],
mode = 'lines',
name="Predicted"
)
data = [trace_open,trace_high]
layout = go.Layout(title="Linear Regression Model",xaxis_rangeslider_visible=True)
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
Support Vector Regression (SVR) is a type of Support Vector Machine, and is a type of supervised learning algorithm that analyzes data for regression analysis.
Pros:
Cons:
# Split the data into 75% training and 25% testing
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# Create and train the Support Vector Machine (Regressor)
svr_rbf = SVR(kernel='rbf', C=1e3, gamma=0.1)
svr_rbf.fit(x_train, y_train)
# Testing Model: Score returns the coefficient of determination R^2 of the prediction.
# The best possible score is 1.0
svm_confidence = svr_rbf.score(x_test, y_test)
print("svm confidence: ", svm_confidence)
# Print support vector regressor model predictions for the next '30' days
svm_prediction = svr_rbf.predict(x_forecast)
print(svm_prediction)
svm_pred_dict = dict(enumerate(svm_prediction.flatten(), 1))
forecast['svm_prediction'] = svm_pred_dict.values()
#Visualize the data
predictions = svm_prediction
#Plot the data
valid = df1[X.shape[0]:]
valid['Predictions'] = predictions #Create a new column called 'Predictions' that will hold the predicted prices
plt.figure(figsize=(25,8))
plt.title('Model')
plt.xlabel('Days',fontsize=18)
plt.ylabel('Close Price USD ($)',fontsize=18)
plt.plot(df1['Close'])
plt.plot(valid[['Close','Predictions']])
plt.legend(['Train', 'Val', 'Prediction' ], loc='upper right')
plt.show()
trace_open = go.Scatter(
x = df.iloc[-30:, 0],
y = forecast['x_forecast'],
mode = 'lines',
name="True",
)
trace_high = go.Scatter(
x = df.iloc[-30:, 0],
y = forecast['svm_prediction'],
mode = 'lines',
name="Predicted"
)
data = [trace_open,trace_high]
layout = go.Layout(title="SVM Model",xaxis_rangeslider_visible=True)
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
We are going to create an ARIMA model and will train it with the closing price of the stock on the train data. So let us split the data into training and test set and visualize it.
#split data into train and training set
train_data, test_data = df_log[3:int(len(df_log)*0.95)], df_log[int(len(df_log)*0.95):]
plt.figure(figsize=(10,6))
plt.grid(True)
plt.xlabel('Dates')
plt.ylabel('Closing Prices')
plt.plot(df_log, 'green', label='Train data')
plt.plot(test_data, 'blue', label='Test data')
plt.legend()
In an ARIMA model there are 3 parameters that are used to help model the major aspects of a times series: seasonality, trend, and noise. These parameters are labeled p,d,and q.
Auto ARIMA: Automatically discover the optimal order for an ARIMA model.
The auto_arima function seeks to identify the most optimal parameters for an ARIMA model, and returns a fitted ARIMA model. This function is based on the commonly-used R function, forecast::auto.arima.
The auro_arima function works by conducting differencing tests (i.e., Kwiatkowski–Phillips–Schmidt–Shin, Augmented Dickey-Fuller or Phillips–Perron) to determine the order of differencing, d, and then fitting models within ranges of defined start_p, max_p, start_q, max_q ranges. If the seasonal optional is enabled, auto_arima also seeks to identify the optimal P and Q hyper- parameters after conducting the Canova-Hansen to determine the optimal order of seasonal differencing, D.
model_autoARIMA = auto_arima(train_data, start_p=0, start_q=0,
test='adf', # use adftest to find optimal 'd'
max_p=3, max_q=3, # maximum p and q
m=1, # frequency of series
d=None, # let model determine 'd'
seasonal=False, # No Seasonality
start_P=0,
D=0,
trace=True,
error_action='ignore',
suppress_warnings=True,
stepwise=True)
print(model_autoARIMA.summary())
So the Auto ARIMA model provided the value of p,d, and q as 2,1 and 0 respectively.
Before moving forward, let’s review the residual plots from auto ARIMA.
model_autoARIMA.plot_diagnostics(figsize=(15,8))
plt.show()
Top left: The residual errors seem to fluctuate around a mean of zero and have a uniform variance.
Top Right: The density plot suggest normal distribution with mean zero.
Bottom left: All the dots should fall perfectly in line with the red line. Any significant deviations would imply the distribution is skewed.
Bottom Right: The Correlogram, aka, ACF plot shows the residual errors are not autocorrelated. Any autocorrelation would imply that there is some pattern in the residual errors which are not explained in the model. So you will need to look for more X’s (predictors) to the model.
Overall, it seems to be a good fit. Let’s start forecasting the stock prices.
Next, create an ARIMA model with provided optimal parameters p, d and q.
model = ARIMA(train_data, order=(2, 1, 0))
fitted = model.fit(disp=-1)
print(fitted.summary())
Now let's start forecast the stock prices on the test dataset keeping 95% confidence level.
# Forecast
fc, se, conf = fitted.forecast(126, alpha=0.05) # 95% confidence
fc_series = pd.Series(fc, index=test_data.index)
lower_series = pd.Series(conf[:, 0], index=test_data.index)
upper_series = pd.Series(conf[:, 1], index=test_data.index)
plt.figure(figsize=(12,5), dpi=100)
plt.plot(train_data, label='training')
plt.plot(test_data, color = 'blue', label='Actual Stock Price')
plt.plot(fc_series, color = 'orange',label='Predicted Stock Price')
plt.fill_between(lower_series.index, lower_series, upper_series, color='k', alpha=.10)
plt.title('ARIMA Model')
plt.xlabel('Days')
plt.ylabel('Actual Stock Price')
plt.legend(loc='upper left', fontsize=8)
plt.show()
ar = pd.DataFrame()
ar['fc_series']= fc_series
ar['lower_series'] = lower_series
ar['upper_series'] = upper_series
ar['actual'] = test_data
ar['date'] = df.iloc[-252:, 0]
ar
trace_open = go.Scatter(
x = ar['date'],
y = ar['fc_series'],
mode = 'lines',
name="Forecast"
)
trace_high = go.Scatter(
x = ar['date'],
y = ar['upper_series'],
mode = 'lines',
fill = "tonexty",
line = {"color": "#57b8ff"},
name="Higher uncertainty interval"
)
trace_low = go.Scatter(
x = ar['date'],
y = ar['lower_series'],
mode = 'lines',
fill = "tonexty",
line = {"color": "#57b8ff"},
name="Lower uncertainty interval"
)
trace_close = go.Scatter(
x = ar['date'],
y = ar['actual'],
name="Data values"
)
data = [trace_open,trace_high,trace_low,trace_close]
layout = go.Layout(title="ARIMA Model",xaxis_rangeslider_visible=True)
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
Let us check the commonly used accuracy metrics to judge forecast results:
# report performance
mse = mean_squared_error(test_data, fc)
print('MSE: '+str(mse))
mae = mean_absolute_error(test_data, fc)
print('MAE: '+str(mae))
rmse = math.sqrt(mean_squared_error(test_data, fc))
print('RMSE: '+str(rmse))
mape = np.mean(np.abs(fc - test_data)/np.abs(test_data))
print('MAPE: '+str(mape))
Prophet is a forecasting model which allows to deal with multiple seasonalities. It is an open source software released by Facebook’s Core Data Science team.
df_fc = df[777:2517] # 2014-01-02 date
df_fc.head()
model = Prophet()
df_prophet = df_fc.drop(['Open', 'High', 'Low','Volume', 'Adj Close'], axis=1)
df_prophet.rename(columns={'Close': 'y', 'Date': 'ds'}, inplace=True)
df_prophet.head(10)
model.fit(df_prophet)
future_prices = model.make_future_dataframe(periods=365)
forecast = model.predict(future_prices)
df_forecast = forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']]
df_forecast.head()
trace_open = go.Scatter(
x = df_forecast["ds"],
y = df_forecast["yhat"],
mode = 'lines',
name="Forecast"
)
trace_high = go.Scatter(
x = df_forecast["ds"],
y = df_forecast["yhat_upper"],
mode = 'lines',
fill = "tonexty",
line = {"color": "#57b8ff"},
name="Higher uncertainty interval"
)
trace_low = go.Scatter(
x = df_forecast["ds"],
y = df_forecast["yhat_lower"],
mode = 'lines',
fill = "tonexty",
line = {"color": "#57b8ff"},
name="Lower uncertainty interval"
)
trace_close = go.Scatter(
x = df_prophet["ds"],
y = df_prophet["y"],
name="Data values"
)
data = [trace_open,trace_high,trace_low,trace_close]
layout = go.Layout(title="Prophet Model",xaxis_rangeslider_visible=True)
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
Unlike regression predictive modeling, time series also adds the complexity of a sequence dependence among the input variables.
A powerful type of neural network designed to handle sequence dependence is called recurrent neural networks. The Long Short-Term Memory network or LSTM network is a type of recurrent neural network used in deep learning because very large architectures can be successfully trained.
training_set = df.iloc[:1000, 1:2].values
test_set = df.iloc[1000:, 1:2].values
# Feature Scaling
sc = MinMaxScaler(feature_range = (0, 1))
training_set_scaled = sc.fit_transform(training_set)
# Creating a data structure with 60 time-steps and 1 output
X_train = []
y_train = []
for i in range(60, 1000):
X_train.append(training_set_scaled[i-60:i, 0])
y_train.append(training_set_scaled[i, 0])
X_train, y_train = np.array(X_train), np.array(y_train)
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
#(740, 60, 1)
We will build the LSTM with 50 neurons and 4 hidden layers. Finally, we will assign 1 neuron in the output layer for predicting the normalized stock price. We will use the MSE loss function and the Adam stochastic gradient descent optimizer.
model = Sequential()
#Adding the first LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50, return_sequences = True, input_shape = (X_train.shape[1], 1)))
model.add(Dropout(0.2))
# Adding a second LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50, return_sequences = True))
model.add(Dropout(0.2))
# Adding a third LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50, return_sequences = True))
model.add(Dropout(0.2))
# Adding a fourth LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50))
model.add(Dropout(0.2))
# Adding the output layer
model.add(Dense(units = 1))
# Compiling the RNN
model.compile(optimizer = 'adam', loss = 'mean_squared_error')
# Fitting the RNN to the Training set
model.fit(X_train, y_train, epochs = 100, batch_size = 32)
# Getting the predicted stock price of 2020
dataset_train = df.iloc[:800, 1:2]
dataset_test = df.iloc[800:, 1:2]
dataset_total = pd.concat((dataset_train, dataset_test), axis = 0)
inputs = dataset_total[len(dataset_total) - len(dataset_test) - 60:].values
inputs = inputs.reshape(-1,1)
inputs = sc.transform(inputs)
X_test = []
for i in range(60, 1778):
X_test.append(inputs[i-60:i, 0])
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
print(X_test.shape)
predicted_stock_price = model.predict(X_test)
predicted_stock_price = sc.inverse_transform(predicted_stock_price)
print(predicted_stock_price)
# Visualising the results
plt.figure(figsize=(20, 10))
plt.plot(df.loc[800:, 'Date'],dataset_test.values, color = 'red', label = 'Real XOM Stock Price')
plt.plot(df.loc[800:, 'Date'],predicted_stock_price, color = 'blue', label = 'Predicted XOM Stock Price')
#plt.xticks(np.arange(0,1778,50))
plt.title('LSTM Model')
plt.xlabel('Time')
plt.ylabel('XOM Stock Price')
plt.legend()
plt.show()
df2 = df
df2.loc[800:, 'Predicted'] = predicted_stock_price
df2.loc[800:, 'Closing'] = dataset_test.values
df2 = df2.drop(columns=['Open', 'High', 'Low', 'Close','Adj Close','Volume'], axis = 1)
df2.dropna()
forecast = go.Scatter(
x = df2.loc[800:, 'Date'],
y = df2.loc[800:, 'Predicted'],
mode = 'lines',
name="Forecast"
)
trace_close = go.Scatter(
x = df2.loc[800:, 'Date'],
y = df2.loc[800:, 'Closing'],
mode = 'lines',
name="Data values"
)
data = [forecast,trace_close]
layout = go.Layout(title="LSTM Model",xaxis_rangeslider_visible=True)
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
Huge drop in March 2020 due to the COVID-19 lockdown ! We can clearly see that our model performed very good. It is able to accuretly follow most of the unexcepted jumps/drops however, for the most recent date stamps, we can see that the model expected (predicted) higher values compared to the real values of the stock price.
from pandas_datareader import data, wb
start = datetime.datetime(2010,11,30)
end = datetime.datetime(2020,11,30)
ticker = "XOM"
xom =data.DataReader(ticker,'yahoo',start,end)
start = datetime.datetime(2010,11,30)
end = datetime.datetime(2020,11,30)
ticker = "CVX"
cvx =data.DataReader(ticker,'yahoo',start,end)
start = datetime.datetime(2010,11,30)
end = datetime.datetime(2020,11,30)
ticker = "VLO"
vlo =data.DataReader(ticker,'yahoo',start,end)
start = datetime.datetime(2010,11,30)
end = datetime.datetime(2020,11,30)
ticker = "BP"
bp =data.DataReader(ticker,'yahoo',start,end)
comp = pd.DataFrame()
comp['xom'] = xom['Close']
comp['cvx'] = cvx['Close']
comp['vlo'] = vlo['Close']
comp['bp'] = bp['Close']
comp.reset_index(inplace = True)
comp
trace_xom = go.Scatter(
x = comp["Date"],
y = comp["xom"],
mode = 'lines',
name="XOM"
)
trace_cvx = go.Scatter(
x = comp["Date"],
y = comp["cvx"],
mode = 'lines',
name="CVX"
)
trace_vlo = go.Scatter(
x = comp["Date"],
y = comp["vlo"],
mode = 'lines',
name="VLO"
)
trace_bp = go.Scatter(
x = comp["Date"],
y = comp["bp"],
mode = 'lines',
name="BP"
)
data = [trace_xom,trace_cvx,trace_vlo,trace_bp]
layout = go.Layout(title="ExxonMobil's Competitors Stock Price",xaxis_rangeslider_visible=True)
fig = go.Figure(data=data,layout=layout)
plotly.offline.iplot(fig)
An Exxon bankruptcy is extremely unlikely in the near term. As it stands, the organization has one of the strongest balance sheets among its integrated peers. The debt-to-equity ratio of Exxon is approximately 0.38 times. While Chevron (NYSE:CVX) is 0.25 times lower, all European players have a much higher debt-to-equity ratio. At the top of the graph, BP is around 1.1 times. The fact is that 0.38 times is actually a reasonably respectable amount, leaving Exxon with plenty of space on its balance sheet to handle more adversity.
It is not wise for one to invest in ExxonMobil's stock right now, considering all the above factors.
Project by - Sanjana Sreenivas Athreya
RUID - 198000887